Micron Document
🎖️GitЯра🎖️

Node / meshtastic / Meshtastic-Android / files / feature / car / src / test / kotlin / org / meshtastic / feature / car / CarScreensTest.kt

Displaying Raw • Download

feature/car/src/test/kotlin/org/meshtastic/feature/car/CarScreensTest.kt 4e48e64e786b58d7c73280f7aa6ebf55be9e53e5 (4e48e64e) Text, 6.35 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffINVISIBLE_REFERENCETa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffINVISIBLE_MEMBERTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.feature.car

Tff7b72import T7ee787androidx.car.app.model.PaneTemplate
Tff7b72import T7ee787androidx.car.app.model.TabTemplate
Tff7b72import T7ee787androidx.car.app.testing.TestCarContext
Tff7b72import T7ee787dev.mokkery.MockMode
Tff7b72import T7ee787dev.mokkery.answering.returns
Tff7b72import T7ee787dev.mokkery.every
Tff7b72import T7ee787dev.mokkery.mock
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.runBlocking
Tff7b72import T7ee787okio.ByteString.Companion.encodeUtf8
Tff7b72import T7ee787org.junit.Assert.assertEquals
Tff7b72import T7ee787org.junit.Assert.assertTrue
Tff7b72import T7ee787org.junit.Test
Tff7b72import T7ee787org.junit.runner.RunWith
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.DataPacket
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.repository.usecase.SendMessageUseCase
Tff7b72import T7ee787org.meshtastic.feature.car.alerts.EmergencyHandler
Tff7b72import T7ee787org.meshtastic.feature.car.model.CarSessionState
Tff7b72import T7ee787org.meshtastic.feature.car.model.ChannelUi
Tff7b72import T7ee787org.meshtastic.feature.car.model.MessagingUiState
Tff7b72import T7ee787org.meshtastic.feature.car.screens.HomeScreen
Tff7b72import T7ee787org.meshtastic.feature.car.service.CarStateCoordinator
Tff7b72import T7ee787org.meshtastic.feature.car.util.MessageFilter
Tff7b72import T7ee787org.meshtastic.proto.PortNum
Tff7b72import T7ee787org.robolectric.RobolectricTestRunner
Tff7b72import T7ee787org.robolectric.RuntimeEnvironment
Tff7b72import T7ee787org.robolectric.annotation.Config

T8b949e/**
* Drives the real [HomeScreen] (via the androidx.car.app testing context) with state pushed through the
* [CarStateCoordinator] test seam, asserting the correct template renders per connection state, and verifies the
* emergency flow turns an ALERT_APP packet into an [org.meshtastic.feature.car.model.EmergencyAlert].
*/
Tf0883e@RunWithTb4b4b4(Te6edf3RobolectricTestRunnerTff7b72::Te6edf3classTb4b4b4)
Tf0883e@ConfigTb4b4b4(Te6edf3sdk Tff7b72= Tff7b72[T79c0ff3T79c0ff6Tff7b72]Tb4b4b4) T8b949e// Robolectric has no SDK 37 jar yet; the car templates are SDK-agnostic.
Tff7b72class T56d364CarScreensTest Tb4b4b4{

Tff7b72private Tff7b72val Te6edf3packetRepo Tff7b72= Te6edf3mockTff7b72<Te6edf3PacketRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)
Tff7b72private Tff7b72val Te6edf3nodeRepo Tff7b72= Te6edf3mockTff7b72<Te6edf3NodeRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)

Tff7b72private Tff7b72fun Td2a8ffcoordinatorTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3CarStateCoordinator Tb4b4b4{
Te6edf3every Tb4b4b4{ Te6edf3packetRepoTb4b4b4.Te6edf3getContactsTb4b4b4(Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3flowOfTb4b4b4(Te6edf3emptyMapTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeRepoTb4b4b4.Te6edf3nodeDBbyNum Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Te6edf3emptyMapTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3CarStateCoordinatorTb4b4b4(
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepoTb4b4b4,
Te6edf3packetRepository Tff7b72= Te6edf3packetRepoTb4b4b4,
Te6edf3serviceRepository Tff7b72= Te6edf3mockTff7b72<Te6edf3ServiceRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3radioConfigRepository Tff7b72= Te6edf3mockTff7b72<Te6edf3RadioConfigRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3sendMessageUseCase Tff7b72= Te6edf3mockTff7b72<Te6edf3SendMessageUseCaseTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3messageFilter Tff7b72= Te6edf3MessageFilterTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffhomeScreenTb4b4b4(Te6edf3coordTb4b4b4: Te6edf3CarStateCoordinatorTb4b4b4)Tb4b4b4: Te6edf3HomeScreen Tb4b4b4{
Tff7b72val Te6edf3ctx Tff7b72= Te6edf3TestCarContextTb4b4b4.Te6edf3createCarContextTb4b4b4(Te6edf3RuntimeEnvironmentTb4b4b4.Te6edf3getApplicationTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3HomeScreenTb4b4b4(Te6edf3ctxTb4b4b4, Te6edf3coordTb4b4b4, Te6edf3EmergencyHandlerTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffsessionTb4b4b4(Te6edf3stateTb4b4b4: Te6edf3ConnectionStateTb4b4b4) Tff7b72= Te6edf3CarSessionStateTb4b4b4(
Te6edf3connectionStatus Tff7b72= Te6edf3stateTb4b4b4,
Te6edf3onlineNodeCount Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3lastMessageTime Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3activeEmergencies Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3meshName Tff7b72= Ta5d6ff"Ta5d6ffTest MeshTa5d6ff"Tb4b4b4,
Tb4b4b4)

Tf0883e@Test
Tff7b72fun Td2a8ff`disconnected renders a pane template`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3coord Tff7b72= Te6edf3coordinatorTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3setStateForTestTb4b4b4(Te6edf3session Tff7b72= Te6edf3sessionTb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3DisconnectedTb4b4b4)Tb4b4b4) Tb4b4b4}
Te6edf3assertTrueTb4b4b4(Te6edf3homeScreenTb4b4b4(Te6edf3coordTb4b4b4)Tb4b4b4.Te6edf3onGetTemplateTb4b4b4(Tb4b4b4) Tff7b72is Te6edf3PaneTemplateTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`connected with no channels renders the onboarding pane`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3coord Tff7b72=
Te6edf3coordinatorTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3setStateForTestTb4b4b4(
Te6edf3session Tff7b72= Te6edf3sessionTb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3ConnectedTb4b4b4)Tb4b4b4,
Te6edf3messaging Tff7b72= Te6edf3MessagingUiStateTb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4, Tff7b72nullTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3assertTrueTb4b4b4(Te6edf3homeScreenTb4b4b4(Te6edf3coordTb4b4b4)Tb4b4b4.Te6edf3onGetTemplateTb4b4b4(Tb4b4b4) Tff7b72is Te6edf3PaneTemplateTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`connected with channels renders the tab template`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3coord Tff7b72=
Te6edf3coordinatorTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3setStateForTestTb4b4b4(
Te6edf3session Tff7b72= Te6edf3sessionTb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3ConnectedTb4b4b4)Tb4b4b4,
Te6edf3messaging Tff7b72= Te6edf3MessagingUiStateTb4b4b4(Te6edf3listOfTb4b4b4(Te6edf3ChannelUiTb4b4b4(T79c0ff0Tb4b4b4, Ta5d6ff"Ta5d6ffLongFastTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4, Tff7b72nullTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3assertTrueTb4b4b4(Te6edf3homeScreenTb4b4b4(Te6edf3coordTb4b4b4)Tb4b4b4.Te6edf3onGetTemplateTb4b4b4(Tb4b4b4) Tff7b72is Te6edf3TabTemplateTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`ALERT_APP packet becomes an emergency alert`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runBlocking Tb4b4b4{
Te6edf3every Tb4b4b4{ Te6edf3nodeRepoTb4b4b4.Te6edf3nodeDBbyNum Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Te6edf3emptyMapTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3alert Tff7b72=
Te6edf3DataPacketTb4b4b4(
Te6edf3to Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3bytes Tff7b72= Ta5d6ff"Ta5d6ffHELPTa5d6ff"Tb4b4b4.Te6edf3encodeUtf8Tb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3dataType Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3ALERT_APPTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3from Tff7b72= Ta5d6ff"Ta5d6ff!abcd1234Ta5d6ff"Tb4b4b4,
Te6edf3time Tff7b72= T79c0ff1T79c0ff0T79c0ff0LTb4b4b4,
Te6edf3id Tff7b72= T79c0ff7Tb4b4b4,
Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3packetRepoTb4b4b4.Te6edf3getContactsTb4b4b4(Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3flowOfTb4b4b4(Te6edf3mapOfTb4b4b4(Ta5d6ff"Ta5d6ffkTa5d6ff" Te6edf3to Te6edf3alertTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3coord Tff7b72=
Te6edf3CarStateCoordinatorTb4b4b4(
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepoTb4b4b4,
Te6edf3packetRepository Tff7b72= Te6edf3packetRepoTb4b4b4,
Te6edf3serviceRepository Tff7b72= Te6edf3mockTff7b72<Te6edf3ServiceRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3radioConfigRepository Tff7b72= Te6edf3mockTff7b72<Te6edf3RadioConfigRepositoryTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3sendMessageUseCase Tff7b72= Te6edf3mockTff7b72<Te6edf3SendMessageUseCaseTff7b72>Tb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)Tb4b4b4,
Te6edf3messageFilter Tff7b72= Te6edf3MessageFilterTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3emergency Tff7b72= Te6edf3coordTb4b4b4.Te6edf3emergencyAlertsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffHELPTa5d6ff"Tb4b4b4, Te6edf3emergencyTb4b4b4.Te6edf3messageTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ff!abcd1234Ta5d6ff"Tb4b4b4, Te6edf3emergencyTb4b4b4.Te6edf3nodeNameTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3emergencyTb4b4b4.Te6edf3isActiveTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.4 - Generated in 0.07s